from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols import basic


def coroutine(func):
    def wrapper(*a, **k):
        g = func(*a, **k)
        assert g.next() is None
        return g
    return wrapper

class ChatServer(basic.NetstringReceiver):
    def connectionMade(self):
        self.username = None
        self.state = self.stateMachine()
    def connectionLost(self, reason):
        self.factory.removeClient(self)
        if self.username is not None:
            self.factory.broadcast("system", "goodbye %s" % (self.username,))
            self.username = None
    def stringReceived(self, data):
        self.state.send(data)
    def sendMessage(self, data):
        self.sendString(data)
    
    @coroutine
    def stateMachine(self):
        self.username = yield
        self.factory.broadcast("system", "hello %s" % (self.username,))
        self.factory.addClient(self)
        while True:
            message = yield
            self.factory.broadcast(self.username, message)


class ChatServerFactory(ServerFactory):
    protocol = ChatServer
    
    def __init__(self):
        self.clients = []
    def addClient(self, client):
        self.clients.append(client)
    def removeClient(self, client):
        self.clients.remove(client)
    
    def broadcast(self, username, message):
        data = "[%s] %s" % (username, message)
        for c in self.clients:
            c.sendMessage(data)


reactor.listenTCP(10250, ChatServerFactory())
reactor.run()






